package training.hari.innerclasses;

/***
 * Inner classes demo. Depicts various type of inner classses. 1. static nested
 * class 2. Inner class 3. Local class 4. Anonymous inner class.
 * 
 * Please make sure you observe the difference in the naming of the genrated
 * byte code/.class files. you will notice interesting difference with inner
 * classes taking $ prefix along with out class name.
 * 
 * @author harinath
 * 
 */
public class OuterClass {

	public void sayHello() {
		System.out.println("Hello");

		HelloWorld hw = new HelloWorld() {

			@Override
			public void sayHelloWorld() {
				System.out.println("Hello World");

			}
		};

		hw.sayHelloWorld();

		// You can even extend existing classes, not just interfaces.
		HelloWorldImpl impl = new HelloWorldImpl() {
			@Override
			public void sayHello() {

				super.sayHello();
				// say what ever you want.
			}
		};

		impl.sayHello();

		// Anonymous inner class. Here we implement the interface, but give no
		// name to the class. so object creation and implementation of interface
		// go
		// hand in hand. see the new HelloWorld(){ this means we are creating
		// object and at the same time we are also implementing the interface.
		// looks different but it is implementation of the interface.
		HelloWorld hw1 = new HelloWorld() {

			@Override
			public void sayHelloWorld() {
				System.out.println("Hello World");

			}
		};

		hw1.sayHelloWorld();

	}

	public void sayHi() {

		InnerClass myInnerObject = new InnerClass();
		myInnerObject.sayInnerHello();

		// Local class. Scope is limited to the method where this class is
		// declared.
		class ClassWithinAMethod {
			public void sayHelloFromMethodClass() {
				System.out.println("hello from class within a method");
			}
		}

		ClassWithinAMethod classWithinMethod = new ClassWithinAMethod();
		classWithinMethod.sayHelloFromMethodClass();

	}

	/**
	 * Inner class/Regular inner class.
	 * 
	 * @author harinath
	 * 
	 */
	public class InnerClass {
		public void sayInnerHello() {
			System.out.println("Hello from Inner class");

		}
	}

	/**
	 * Static nested class
	 * 
	 * @author harinath
	 * 
	 */
	public static class StaticInnerClass {
		public void sayStaticInnerHello() {
			System.out.println("Hello from static inner class");
		}
	}

}
